home *** CD-ROM | disk | FTP | other *** search
/ Trading on the Edge / Trading On The Edge - CD-ROM Toolkit (Wayzata Technology)(2031)(1994).bin / mac / Shared / AZTE programs / control.c next >
C/C++ Source or Header  |  1993-06-11  |  38KB  |  1,821 lines

  1. /* 10/5/89.
  2.  * Control routines for a Double Oral Auction player program
  3.  * C version.        R.G. Palmer, Jan-Mar 1989.
  4.  *
  5.  * *** See comments in skeleton.c, define.h, and README for details. ***
  6.  *
  7.  * You must customize define.h before compiling, but should not need
  8.  * to change this file at all.
  9.  *
  10.  * Note: this version has some experimental code for running on a PC talking
  11.  * (via the serial port) to DANI on a mainframe etc.  But it doesn't yet work.
  12.  * It should have no effect unless you try to use PIPEBASED on a PC.
  13.  */  
  14.  
  15. #include "define.h"
  16.  
  17. #ifdef BSD43
  18. #define UNIX 1
  19. #define RAND_MAX 2147483647
  20. #endif
  21.  
  22. #ifdef SUN3
  23. #define UNIX 1
  24. #define RAND_MAX 2147483647
  25. char * sprintf();    /* for lint */
  26. #endif
  27.  
  28. #ifdef SUN4
  29. #define UNIX 1
  30. #define RAND_MAX 2147483647
  31. char * sprintf();    /* for lint */
  32. #endif
  33.  
  34. #ifdef CRAY
  35. #define UNIX 1
  36. #define RAND_MAX 32767
  37. #endif
  38.  
  39. #ifdef IRIS
  40. #define UNIX 1
  41. #define RAND_MAX 32767
  42. #endif
  43.  
  44. #ifdef TURBOC
  45. #define MSDOS 1
  46. #define ANSI  1
  47. #endif
  48.  
  49. #ifdef QUICKC
  50. #define MSDOS 1
  51. #define ANSI  1
  52. #endif
  53.  
  54. #ifdef VMS
  55. #define ANSI_OR_VMS    1
  56. #define RAND_MAX 2147483647
  57. #define GOODEXIT    1
  58. #define WARNEXIT    0
  59. #define BADEXIT        2
  60. #ifdef INETBASED
  61. #define NETRW 1
  62. #endif
  63. #else
  64. #define GOODEXIT    0
  65. #define WARNEXIT    1
  66. #define BADEXIT        2
  67. #endif
  68.  
  69. #ifdef THINKC3
  70. #define THINKC    1
  71. #define RAND_MAX    32767
  72. #define TZHOURS    5
  73. #else
  74. #define TZHOURS    0
  75. #endif
  76.  
  77. #ifdef THINKC4
  78. #define THINKC    1
  79. #define ANSI    1
  80. #endif
  81.  
  82. #ifdef THINKC
  83. #define ALWAYSDELIN    1
  84. #ifdef INETBASED 
  85.     <<Inet-based not possible on a Mac>>
  86. #endif
  87. #endif
  88.  
  89. #ifdef ANSI
  90. #define ANSI_OR_VMS    1
  91. #endif
  92.  
  93. #ifdef ANSI_OR_VMS
  94. #define REMOVE    remove
  95. #else
  96. #define REMOVE    unlink
  97. #endif
  98.  
  99. #ifdef MSDOS
  100. #ifdef INETBASED 
  101.     <<Inet-based not possible on a PC>>
  102. #endif
  103. #endif
  104.  
  105. #ifdef NETRW
  106. #define READ netread
  107. #define WRITE netwrite
  108. #else
  109. #define READ read
  110. #define WRITE write
  111. #endif
  112.  
  113. /* includes */
  114. #include <stdio.h>
  115. #include <pwd.h>
  116.  
  117. #ifdef THINKC3
  118. #include <strings.h>
  119. #include <unix.h>
  120. #else
  121. #include <strings.h>
  122. #include <time.h>
  123. #endif
  124.  
  125. #ifdef THINKC4
  126. #include <console.h>
  127. #endif
  128.  
  129. #ifdef ANSI
  130. #include <stddef.h>
  131. #ifndef NO_STDLIB_H
  132. #include <stdlib.h>
  133. #endif
  134. #endif
  135.  
  136. #ifdef MSDOS
  137. #include <sys\types.h>
  138. #else
  139. #ifdef VMS
  140. #ifdef INETBASED
  141. #include <sys/types.h>
  142. #else
  143. #include types
  144. #endif
  145. #else
  146. #ifdef THINKC3
  147. #include <types.h>
  148. #else
  149. #ifndef ANSI
  150. #include <sys/types.h>
  151. #endif
  152. #endif
  153. #endif
  154. #endif
  155.  
  156. #ifdef INETBASED
  157. #include <sys/socket.h>    /* for SOCK_... and AF_... constants */
  158. #include <netinet/in.h>    /* for struct sockaddr_in, htons() */
  159. #include <netdb.h>    /* for hostent, gethostbyname... */
  160. #include <errno.h>
  161. #endif
  162.  
  163. /* Various maxima.  Note that these constants are also defined in
  164.  * skeleton.c and human.c, but may have smaller values there if the
  165.  * user wishes to limit array sizes.  The values here should not
  166.  * need to be changed.
  167.  */
  168. #define MAXPLAYERS    20    /* maximum of each, MUST BE EVEN */
  169. #define MAXROUNDS    20
  170. #define MAXPERIODS    5
  171. #define MAXTIMES    400
  172. #define MAXTOKENS    4    /* MUST BE EVEN */
  173.  
  174. #define MAXFILENAME    20
  175.  
  176. /* Global variables (see comments in skeleton) */
  177. int nplayers = 0;
  178. int nbuyers = 0;
  179. int nsellers = 0;
  180. int bnumber[MAXPLAYERS+1];
  181. int snumber[MAXPLAYERS+1];
  182. int nrounds = 0;
  183. int nperiods = 0;
  184. int ntimes = 0;
  185. int minprice = 0;
  186. int maxprice = 8000;
  187. int gameid = 0;
  188. int gametype = 0;
  189. int r = 0;
  190. int p = 0;
  191. int t = 0;
  192. int cbid = 0;
  193. int coffer = 0;
  194. int bidder = 0;
  195. int offerer = 0;
  196. int nbids = 0;
  197. int noffers = 0;
  198. int bids[MAXPLAYERS+1];
  199. int offers[MAXPLAYERS+1];
  200. int bstype = 0;
  201. int price = 0;
  202. int buyer = 0;
  203. int seller = 0;
  204. int btrades[MAXPLAYERS+1];
  205. int strades[MAXPLAYERS+1];
  206. int ntrades = 0;
  207. int prices[MAXPLAYERS*MAXTOKENS+1];
  208. int lasttime = 0;
  209. int id = 0;
  210. int role = 0;
  211. int timeout = 0;
  212. int ntokens = 0;
  213. int token[MAXTOKENS+1];
  214. int mytrades = 0;
  215. int mylasttime = 0;
  216. int pprofit = 0;
  217. int rprofit = 0;
  218. int gprofit = 0;
  219. int nobidoff = 0;
  220. int bo = 0;
  221. int nobuysell = 0;
  222. int bs = 0;
  223. int late = 0;
  224. int tradelist[MAXPERIODS+1];
  225. int profitlist[MAXPERIODS+1];
  226. int efficiency = 0;    /* doesn't need to be saved -- after END only */
  227. int noblock = 0;    /* internal variable, must be saved if FILEBASED */
  228.  
  229. extern int hmtype;    /* 1 for human, 2 for machine */
  230.  
  231. /* newvars */
  232. int havegametype;
  233. float payment_rate, payment_base;
  234. int clearingrule = 0;
  235.  
  236. /* Declaration of all routines */
  237.  
  238. /* External -- must be in user's part */
  239. extern void gbegin(),gend(),rbegin(),rend();
  240. extern void pbegin(),pend(),boend(),bsend();
  241. extern void exp_value();
  242. extern int bid(),offer(),buy(),sell();
  243. extern void getparams();
  244. extern void setnoblock(),resetterm();
  245. extern void rantok_main();
  246. extern void intro_chart();
  247. #ifdef INETBASED
  248. extern int getrole();
  249. extern void getpname();
  250. #endif
  251. #ifdef FILEBASED
  252. extern void savedata(),retrievedata();
  253. #endif
  254.  
  255. /* Internal */
  256. static void init1(),init2(),round(),endround(),period(),endperiod();
  257. static void bidoff(),boresult(),buysell(),bsresult(),gameend(),killed();
  258. static void initvars(),clearbo(),getmess(),expect(),sendmess();
  259. static void stripcopy(),randset(),adios();
  260. double drand();
  261. void error();
  262. /* new routines */
  263. void header();
  264. void get_gamedata();
  265. void get_gamehist();
  266. void get_players();
  267. static void sleep();
  268. int sock_gets();
  269. void menu();
  270. void print_menu();
  271. void show_payment_rates();
  272. void show_clearingrule();
  273. void show_descriptions();
  274. void show_players();
  275. void show_gamehist();
  276. void display_file();
  277. int line_count();
  278. void waitkey();
  279.  
  280.  
  281.  
  282.  
  283. #ifdef FILEBASED
  284. static void filesetup();
  285. void readarray(),writearray();
  286. #endif
  287. #ifdef PIPEBASED
  288. static void pipesetup();
  289. #endif
  290. #ifdef INETBASED
  291. int inetsetup();
  292. #endif
  293. #ifdef DISPLAY
  294. void twolinehead(),showcurrent(),showprices(),nl();
  295. static void nput();
  296. #endif
  297.  
  298. /* names local to this file (no need to save in FILEBASED) */
  299. static int mtype = 0;
  300. static int mpar1 = 0;
  301. static int mpar2 = 0;
  302. static char progname[MAXFILENAME-4];
  303. #ifdef THINKC4
  304. static char pprogname[MAXFILENAME-4];  /* Pascal copy */
  305. #endif
  306.  
  307. int waitforreturn = 0;    /* for THINKC: forces wait for CR on exit if set */
  308.  
  309. #ifdef FILEBASED
  310. static char inname[MAXFILENAME];
  311. static char outname[MAXFILENAME];
  312. static FILE *outfile = NULL;
  313. static FILE *infile = NULL;
  314. FILE *savefile = NULL;
  315. #else
  316. #ifndef MSDOS
  317. int outfd = -1;
  318. int infd = -1;
  319. #else
  320. /* experimental code */
  321. char auxbuf[100];
  322. #endif
  323. #endif
  324.  
  325. #ifdef DISPLAY
  326. #define DSPLY    1
  327. #define BUYCHAR '<'
  328. #define SELLCHAR '>'
  329. #define DISPLAY_OR_INET    1
  330. #else
  331. #define DSPLY    0
  332. #ifdef INETBASED
  333. #define DISPLAY_OR_INET    1
  334. #endif
  335. #endif
  336.  
  337. #define EOS  '\0'
  338. #define BELL 07
  339.  
  340. #define RINT register int
  341.  
  342. /* code table for messages */
  343. #define ACCEPT    1
  344. #define BID    2
  345. #define BIDOFF    3
  346. #define BODISP    4
  347. #define BSDISP    5
  348. #define BUY    6
  349. #define BUYERS  29
  350. #define BUYSELL    7
  351. #define CBID    8
  352. #define COFFER    9
  353. #define END    10
  354. #define GAME    11
  355. #define KILLED    98
  356. #define LENGTH    12
  357. #define LIMITS    13
  358. #define NONE    14
  359. #define NUMBER    15
  360. #define OFFER    16
  361. #define PERIOD    17
  362. #define PLAYER    18
  363. #define PRICES    19
  364. #define QUIT    99
  365. #define READY    20
  366. #define REFUSE    21
  367. #define ROLE    22
  368. #define ROUND    27
  369. #define SELL    23
  370. #define SELLERS 30
  371. #define TEST    31
  372. #define TOKENS  28
  373. #define TRADE    24
  374. #define TRADERS    25
  375. #define TYPE    26
  376.  
  377. main(argc,argv)
  378. int argc;
  379. char *argv[];
  380. {
  381.  
  382. /* get program name, stripped of directories and extension */
  383. #ifdef PROGNAME
  384.     stripcopy(progname,PROGNAME,MAXFILENAME-5);
  385. #else
  386. #ifdef THINKC
  387.     {
  388.     char apName[256];
  389.     int apRefNum;
  390.     Handle apParam;
  391.     GetAppParms(apName,&apRefNum,&apParam);
  392.     PtoCstr(apName);
  393.     stripcopy(progname,apName,MAXFILENAME-5);
  394. #ifdef THINKC3
  395.     Click_On(FALSE);
  396. #else
  397.     console_options.top = 60;
  398.     console_options.nrows = 16; 
  399.     strcpy(pprogname,progname);
  400.     CtoPstr(pprogname);
  401.     console_options.title = pprogname;
  402.     console_options.pause_atexit = 0;
  403. #endif
  404.     }
  405. #else
  406.     stripcopy(progname,argv[0],MAXFILENAME-5);
  407. #ifdef FILEBASED
  408.     if (strcmp(argv[0],"a.out")==0)
  409.     error("*program name cannot end in .out");
  410. #endif
  411. #endif
  412. #endif
  413.  
  414. /* Set up input and output file pointers (FILEBASED) or
  415.  * file descriptors (PIPEBASED or INETBASED).
  416.  */
  417. #ifdef PIPEBASED
  418. #ifdef MSDOS
  419. /* experimental code */
  420.     puts("Type your command to start dani.  Use the -u option.\n");
  421.     fgets(auxbuf,100,stdin);
  422.     fputs(auxbuf,stdaux);
  423. #else
  424.     pipesetup(argc,argv);
  425. #endif
  426. #endif
  427. #ifdef FILEBASED
  428.     filesetup(argc);
  429. #endif
  430. #ifdef INETBASED
  431.     if (argc>=2) {
  432.     if (inetsetup(argv[1],atoi(argv[2]),DSPLY))
  433.         adios(WARNEXIT,0,0);
  434.     }
  435.     else {
  436.     if (inetsetup(NULL,0,DSPLY))
  437.         adios(WARNEXIT,0,0);
  438.     }
  439. #endif
  440.  
  441. /* menu options */
  442.     header();
  443.     printf("\nPress Enter/Return to begin...\n");
  444.     waitkey();
  445.     menu();
  446.  
  447. /* play a game */
  448.  
  449.     WRITE(outfd,"ready\n",strlen("ready\n"));
  450.  
  451. /* main loop to read a message and branch accordingly */
  452.  
  453.     /* read a message */
  454.     getmess(&mtype,&mpar1,&mpar2);
  455.  
  456. #ifdef FILEBASED
  457.     /* read our saved variables if filebased unless init-1 or KILLED or TEST */
  458.     if (mtype != TYPE && mtype != KILLED && mtype != TEST) {
  459.     outfile = fopen(outname,"r+");
  460.     if (outfile == NULL) {
  461.         if (mtype != END) error("can't open .out file");
  462.     }
  463.     else {
  464.         int c;
  465.         while ((c=getc(outfile))!=EOF && c!='\n') ; /* skip old output */
  466.         savefile = outfile;
  467.         retrievedata();
  468.         rewind(outfile);
  469.         randset();    /* set up random number generator */
  470.         if (noblock)
  471.         setnoblock();    /* restore non-blocking mode if needed */
  472.     }
  473.     }
  474. #endif
  475.  
  476.     /* branch on type of (first) message */
  477.     while (1) {
  478.     switch (mtype) {
  479.     case TYPE:
  480.         init1();
  481.         break;
  482.     case NUMBER:
  483.         init2();
  484.         break;
  485.     case ROUND:
  486.         if (p>0) endperiod();    /* end of previous period */
  487.         if (r>0) endround();    /* end of previous round */
  488.         round();
  489.         break;
  490.     case PERIOD:
  491.         if (p>0) endperiod();    /* end of previous period */
  492.         period();
  493.         break;
  494.     case BIDOFF:
  495.         bidoff();
  496.         break;
  497.     case BODISP:
  498.         boresult();
  499.         break;
  500.     case BUYSELL:
  501.         buysell();
  502.         break;
  503.     case BSDISP:
  504.         bsresult();
  505.         break;
  506.     case END:
  507.         if (p>0) endperiod();    /* end of period */
  508.         if (r>0) endround();    /* end of round */
  509.         gameend();            /* end of game */
  510.         adios(GOODEXIT,1,1);
  511.         /*NOTREACHED*/
  512.     case KILLED:
  513.         killed();
  514.         /*NOTREACHED*/
  515.     case TEST:
  516.         sendmess(TEST,mpar1);
  517.         break;
  518.     default:
  519.         error("unexpected message");
  520.     }
  521.     getmess(&mtype,&mpar1,&mpar2);
  522.     }
  523.     /*NOTREACHED*/
  524. }
  525.  
  526.  
  527. static void
  528. init1()        /* initialization-1 step */
  529. {
  530.     RINT i;
  531.     int ignore,reason;
  532.     int protocol;
  533.     int maxplayers,maxrounds,maxperiods,maxtimes,maxtokens,roles,playernumber;
  534. #ifdef DISPLAY_OR_INET
  535.     static char unacceptable[] = " unacceptable\n";
  536. #endif
  537.  
  538.     protocol = mpar1;
  539.  
  540. /* initialize all arrays explicity */
  541.     for (i=0;i<=MAXPLAYERS;i++) {
  542.     bids[i] = 0;
  543.     offers[i] = 0;
  544.     btrades[i] = 0;
  545.     strades[i] = 0;
  546.     bnumber[i] = 0;
  547.     snumber[i] = 0;
  548.     }
  549.     for (i=0;i<=MAXTOKENS;i++)
  550.     token[i] = 0;
  551.     for (i=0;i<=MAXPLAYERS*MAXTOKENS;i++)
  552.     prices[i] = 0;
  553.     for (i=0;i<=MAXPERIODS;i++) {
  554.     tradelist[i] = 0;
  555.     profitlist[i] = 0;
  556.     }
  557.  
  558. /* get rest of initialization-1 packet */
  559.     expect(GAME,&gametype,&gameid);
  560.     expect(LENGTH,&nrounds,&ignore);
  561.     expect(LENGTH,&nperiods,&ntimes);
  562.     expect(TOKENS,&ntokens,&ignore);
  563.     expect(NUMBER,&nbuyers,&nsellers);
  564.     expect(ROLE,&role,&timeout);
  565.  
  566. /* get user's limits, acceptable roles, and playernumber */
  567.     getparams(&maxplayers,&maxrounds,&maxperiods,&maxtimes,&maxtokens,&roles,
  568.     &playernumber);
  569.     if (maxplayers > MAXPLAYERS) maxplayers = MAXPLAYERS;
  570.     if (maxrounds > MAXROUNDS) maxrounds = MAXROUNDS;
  571.     if (maxperiods > MAXPERIODS) maxperiods = MAXPERIODS;
  572.     if (maxtimes > MAXTIMES) maxtimes = MAXTIMES;
  573.     if (maxtokens > MAXTOKENS) maxtokens = MAXTOKENS;
  574.  
  575. /* see if we can play */
  576.     reason = 0;
  577.  
  578. #ifdef DISPLAY_OR_INET
  579.     if (protocol != 5) {
  580.     reason |= 1;
  581.     printf("** protocol %d%s",protocol,unacceptable);
  582.     }
  583.     if (nrounds>maxrounds) {
  584.     reason |= 4;
  585.     printf("** nrounds = %d --%s",nrounds,unacceptable);
  586.     }
  587.     if (nperiods>maxperiods) {
  588.     reason |= 8;
  589.     printf("** nperiods = %d --%s",nperiods,unacceptable);
  590.     }
  591.     if (ntimes>maxtimes) {
  592.     reason |= 16;
  593.     printf("** ntimes = %d --%s",ntimes,unacceptable);
  594.     }
  595.     if (ntokens>maxtokens) {
  596.     reason |= 32;
  597.     printf("** ntokens = %d --%s",ntokens,unacceptable);
  598.     }
  599.     if (nbuyers>maxplayers || nsellers>maxplayers) {
  600.     reason |= 64;
  601.     printf("** nbuyers = %d, nsellers = %d --%s",
  602.         nbuyers,nsellers,unacceptable);
  603.     }
  604.     if (!(role&roles)) {
  605.     reason |= 128;
  606.     printf("** monitor expects a %s\n",(role==1)?"buyer":"seller");
  607.     }
  608.     if (hmtype==1 && timeout<5) {
  609.     reason |= 256;
  610.     printf(
  611.     "** timeout = %d -- too small for human player (missing -h flag?)\n",
  612.     timeout);
  613.     }
  614. #else
  615.     if (protocol != 5) reason |= 1;
  616.     if (nrounds>maxrounds) reason |= 4;
  617.     if (nperiods>maxperiods) reason |= 8;
  618.     if (ntimes>maxtimes) reason |= 16;
  619.     if (ntokens>maxtokens) reason |= 32;
  620.     if (nbuyers>maxplayers || nsellers>maxplayers) reason |= 64;
  621.     if (!(role&roles)) reason |= 128;
  622.     if (hmtype==1 && timeout<5) reason |= 256;
  623. #endif
  624.  
  625. #ifdef DISPLAY
  626.     if (nbuyers+nsellers>MAXDISPLAY) {
  627.     reason |= 64;
  628.     printf("** nbuyers+nsellers = %d -- too large for DISPLAY\n",
  629.         nbuyers+nsellers);
  630.     }
  631. #endif
  632.     
  633. /* send ACCEPT or REFUSE message */
  634.     if (reason != 0) {
  635. #ifdef DISPLAY_OR_INET
  636.     puts("*** refused to play game ***");
  637. #endif
  638.     sendmess(REFUSE,reason);
  639.     adios(WARNEXIT,1,0);
  640.     }
  641.     sendmess(ACCEPT,playernumber);
  642. }
  643.  
  644.  
  645. static void
  646. init2()        /* initialization-2 step */
  647. {
  648.     RINT i;
  649.     int ignore;
  650.  
  651. #ifdef DISPLAY
  652. #ifndef THINKC3
  653.     time_t time();
  654. #endif
  655.     time_t timeval = time((time_t *)0) - (TZHOURS*3600);
  656. #endif
  657.  
  658. /* initialization-2 step */
  659.     nbuyers = mpar1;
  660.     nsellers = mpar2;
  661.     for (i=1; i<=nbuyers; i+=2)
  662.     expect(BUYERS,bnumber+i,bnumber+i+1);
  663.     for (i=1; i<=nsellers; i+=2)
  664.     expect(SELLERS,snumber+i,snumber+i+1);
  665.     expect(LIMITS,&minprice,&maxprice);
  666.     expect(PLAYER,&id,&ignore);
  667.     nplayers = nbuyers+nsellers;
  668.  
  669. /* set up random number generator (uses id) */
  670.     randset();
  671.  
  672. #ifdef DISPLAY
  673.     printf("\nDA game %4d  %s",gameid,ctime(&timeval));
  674.     nput('-',38);
  675.     printf("\nnrounds: %d   nperiods: %d   ntimes: %d   price range: %d-%d\n",
  676.     nrounds,nperiods,ntimes,minprice,maxprice);
  677.     printf("gametype: %04d\n",gametype);
  678.     printf("\n%2d buyer%s ",nbuyers,nbuyers>1?"s:":": ");
  679.     for (i=1; i<=nbuyers; i++) {
  680.     if (i%6==1 && i>1) { nl(); nput(' ',12); }
  681.     printf("    B%-2d %4d",i,bnumber[i]);
  682.     }
  683.     printf("\n%2d seller%s",nsellers,nsellers>1?"s:":": ");
  684.     for (i=1; i<=nsellers; i++) {
  685.     if (i%6==1 && i>1) { nl(); nput(' ',12); }
  686.     printf("    S%-2d %4d",i,snumber[i]);
  687.     }
  688.     printf("\nYou are %s%d, otherwise known as YOU\n",
  689.     role==1?"buyer B":"seller S",id);
  690.     fflush(stdout);
  691.     waitforreturn = 1;
  692. #endif
  693.  
  694.     gbegin();            /* start of game */
  695.     sendmess(READY,id);
  696. }
  697.  
  698.  
  699. static void
  700. round()        /* round step */
  701. {
  702.     RINT i;
  703.  
  704.     r = mpar1;
  705.     ntokens = mpar2;
  706.     for (i=1; i<=ntokens; i+=2)
  707.     expect(PRICES,&token[i],&token[i+1]);
  708.     for (i=ntokens+1; i<=MAXTOKENS; i++)
  709.     token[i] = 0;
  710.     p = 0;
  711.     rprofit = 0;
  712.     initvars();    /* initialize variables */
  713.     for (i=1; i<=MAXPERIODS; i++) {
  714.     tradelist[i] = 0;
  715.     profitlist[i] = 0;
  716.     }
  717.     rbegin();    /* start of round */
  718.     sendmess(READY,id);
  719. }
  720.  
  721.  
  722. static void
  723. endround()    /* end of round */
  724. {
  725. #ifdef DISPLAY
  726.     RINT i;
  727.     int tradesum = 0;
  728.     nl();
  729.     nput('=',20);
  730.     printf(" End of round %d ",r);
  731.     nput('=',20);
  732.     puts("\nSummary:   period  trades  profit");
  733.     for (i=1; i<=p; i++) {
  734.     printf("             %2d       %d     %4d\n",i,tradelist[i],
  735.         profitlist[i]);
  736.     tradesum += tradelist[i];
  737.     }
  738.     printf("            total     %d     %4d\n\n",tradesum,rprofit);
  739.     fflush(stdout);
  740.     nl();
  741.     waitforreturn = 1;
  742. #endif
  743.     rend();
  744. }
  745.  
  746.  
  747. static void
  748. period()    /* period step */
  749. {
  750.     r = mpar1;
  751.     p = mpar2;
  752.     initvars();    /* initialize variables */
  753.     pbegin();    /* start of period */
  754.     sendmess(READY,id);
  755. }
  756.  
  757.  
  758. static void
  759. endperiod()        /* end of period */
  760. {
  761. #ifdef DISPLAY
  762.     printf("\n--- end of period %d of round %-2d%c",p,r,(r>9)?' ':'-');
  763.     nput('-',47);
  764.     printf("\nYou made %d trades, making a total profit of %d in this period\n",
  765.     mytrades,pprofit);
  766.     showprices();
  767.     waitforreturn = 1;
  768. #endif
  769.  
  770.     pend();
  771. }
  772.  
  773.  
  774. static void
  775. bidoff()    /* bid-offer step */
  776. {
  777.     int value;
  778.  
  779.     t = mpar1;
  780.     nobidoff = mpar2;
  781.  
  782. #ifdef DISPLAY
  783.     nl();
  784.     twolinehead();
  785.     waitforreturn = 1;
  786. #endif
  787.     if (role == 1) {
  788.     value = bid();        /* ask the bid routine what to do */
  789.     if (value != 0)
  790.         sendmess(BID,value);
  791.     }
  792.     else {
  793.     value = offer();    /* ask the offer routine what to do */
  794.     if (value != 0)
  795.         sendmess(OFFER,value);
  796.     }
  797.     if (value == 0)
  798.     sendmess(NONE,0);
  799. }
  800.  
  801.  
  802. static void
  803. boresult()    /* process bid-offer result packet */
  804. {
  805. #ifdef DISPLAY
  806.     RINT i;
  807.     char * msg;
  808. #endif
  809.  
  810.     bo = mpar1;
  811.     mytrades = mpar2;
  812.     tradelist[p] = mytrades;
  813.     if (bo == (-2)) {    /* late -- minimize damage to variables */
  814.     ++late;
  815.     bstype = (-1);
  816.     price = 0;
  817.     buyer = 0;
  818.     seller = 0;
  819.     nobidoff = -1;
  820.     nobuysell = -1;
  821.     }
  822.     clearbo();
  823.     while (1) {
  824.     getmess(&mtype,&mpar1,&mpar2);
  825.     if (mtype == BID) {
  826.         bids[mpar2] = mpar1;
  827.         ++nbids;
  828.     }
  829.     else if (mtype == OFFER) {
  830.         offers[mpar2] = mpar1;
  831.         ++noffers;
  832.     }
  833.     else
  834.         break;
  835.     }
  836.     if (mtype != CBID) error("not CBID in boresult");
  837.     cbid = mpar1;
  838.     bidder = mpar2;
  839.     expect(COFFER,&coffer,&offerer);
  840.  
  841. /* tell the user */
  842.     boend();
  843.  
  844. /* display it */
  845. #ifdef DISPLAY
  846.     nput(' ',12);
  847.     for (i=1; i<=nbuyers; i++) {
  848.     if (i == id && role == 1)
  849.         fputs(" YOU",stdout);
  850.     else if (i>=10)
  851.         printf(" B%d",i);
  852.     else
  853.         printf("  B%d",i);
  854.     printf("/%c",btrades[i]<MAXTOKENS?'a'+btrades[i]:'-');
  855.     }
  856.     nput(' ',2);
  857.     for (i=1; i<=nsellers; i++) {
  858.     if (i == id && role == 2)
  859.         fputs(" YOU",stdout);
  860.     else if (i>=10)
  861.         printf(" S%d",i);
  862.     else
  863.         printf("  S%d",i);
  864.     printf("/%c",strades[i]<MAXTOKENS?'a'+strades[i]:'-');
  865.     }
  866.     nl();
  867.     switch (bo) {
  868.     case 2:   msg = "winner      ";  break;
  869.     case 3:   msg = "bettered    ";  break;
  870.     case 4:   msg = "lost tie    ";  break;
  871.     case -1:  msg = "**illegal** ";  break;
  872.     case -2:  msg = "**late**    ";  break;
  873.     default:  msg = "            ";  break;
  874.     }
  875.     fputs(msg,stdout);
  876.     for (i=1; i<=nbuyers; i++) {
  877.     if (bids[i] > 0)
  878.         printf("%5d%c",bids[i],i==bidder?'*':' ');
  879.     else if (i == bidder)
  880.         printf("%5d#",cbid);
  881.     else
  882.         nput(' ',6);
  883.     }
  884.     nput(' ',2);
  885.     for (i=1; i<=nsellers; i++) {
  886.     if (offers[i] > 0)
  887.         printf("%5d%c",offers[i],i==offerer?'*':' ');
  888.     else if (i == offerer)
  889.         printf("%5d#",coffer);
  890.     else
  891.         nput(' ',6);
  892.     }
  893.     nl();
  894.     fflush(stdout);
  895.     waitforreturn = 1;
  896. #endif
  897. }
  898.  
  899.  
  900. static void
  901. buysell()    /* buy-sell step */
  902. {
  903.     int value;
  904.  
  905.     t = mpar1;
  906.     nobuysell = mpar2;
  907.     if (role == 1) {
  908.     value = buy();        /* ask the buy routine what to do */
  909.     if (value != 0)
  910.         sendmess(BUY,coffer);
  911.     }
  912.     else {
  913.     value = sell();        /* ask the sell routine what to do */
  914.     if (value != 0)
  915.         sendmess(SELL,cbid);
  916.     }
  917.     if (value == 0)
  918.     sendmess(NONE,0);
  919. }
  920.  
  921.  
  922. static void
  923. bsresult()    /* process buy-sell result packet */
  924. {
  925.     int profit;
  926. #ifdef DISPLAY
  927.     RINT i;
  928.     char * msg;
  929. #endif
  930.  
  931.     bs = mpar1;
  932.     mytrades = mpar2;
  933.     tradelist[p] = mytrades;
  934.     if (bs == (-2)) {    /* late -- minimize damage to variables */
  935.     ++late;
  936.     clearbo();
  937.     nobidoff = -1;
  938.     nobuysell = -1;
  939.     }
  940.     getmess(&mtype,&mpar1,&mpar2);
  941.     if (mtype == TRADE) {
  942.     bstype = mpar1;
  943.     price = mpar2;
  944.     prices[++ntrades] = mpar2;
  945.     lasttime = t;
  946.     expect(TRADERS,&buyer,&seller);
  947.     btrades[buyer]++;
  948.     strades[seller]++;
  949.     if (id == (role==1?buyer:seller)) {    /* we just made a trade */
  950.         mylasttime = t;
  951.         profit = role==1? token[mytrades]-price : price-token[mytrades];
  952.         pprofit += profit;
  953.         rprofit += profit;
  954.         gprofit += profit;
  955.         profitlist[p] = pprofit;
  956.         prices[ntrades] = -prices[ntrades];    /* to label as ours */
  957.     }
  958.     getmess(&mtype,&mpar1,&mpar2);
  959.     }
  960.     else {
  961.     bstype = 0;
  962.     price = 0;
  963.     buyer = 0;
  964.     seller = 0;
  965.     }
  966.     if (mtype != CBID) error("not CBID in bsresult");
  967.     cbid = mpar1;
  968.     bidder = mpar2;
  969.     expect(COFFER,&coffer,&offerer);
  970.  
  971. /* tell the user */
  972.     bsend();
  973.  
  974. #ifdef DISPLAY
  975.     switch (bs) {
  976.     case 2:   msg = "lost toss   ";  break;
  977.     case 3:   msg = "lost draw   ";  break;
  978.     case -1:  msg = "**illegal** ";  break;
  979.     case -2:  msg = "**late**    ";  break;
  980.     default:  msg = "            ";  break;
  981.     }
  982.     if (bstype>0) {
  983.     if (buyer == id && role == 1)
  984.         printf("profit:%5d",token[mytrades]-price);
  985.     else if (seller == id && role == 2)
  986.         printf("profit:%5d",price-token[mytrades]);
  987.     else
  988.         fputs(msg,stdout);
  989.     for (i=1; i<=nbuyers; i++) {
  990.         if (i == buyer)
  991.         if (bstype == 2)
  992.             printf("%5d%c",price,SELLCHAR);
  993.         else
  994.             printf("    %c ",BUYCHAR);
  995.         else
  996.         nput(' ',6);
  997.     }
  998.     nput(' ',2);
  999.     for (i=1; i<=nsellers; i++) {
  1000.         if (i == seller) {
  1001.         if (bstype == 1)
  1002.             printf("%5d%c",price,BUYCHAR);
  1003.         else
  1004.             printf("    %c ",SELLCHAR);
  1005.         break;
  1006.         }
  1007.         else
  1008.         nput(' ',6);
  1009.     }
  1010.     nl();
  1011.     }
  1012.     else if (bs < 0)
  1013.     puts(msg);
  1014.     else
  1015.     puts("no trade");
  1016.     fflush(stdout);
  1017.     waitforreturn = 1;
  1018. #endif
  1019. }
  1020.  
  1021.  
  1022. static void
  1023. gameend()    /* end of game step */
  1024. {
  1025.     efficiency = mpar2;
  1026. #ifdef DISPLAY
  1027.     nl();
  1028.     nput('=',30);
  1029.     printf(" End of game %d ",gameid);
  1030.     nput('=',31);
  1031.     printf("\nTotal profit: %d",mpar1);
  1032.     if (gprofit != mpar1) {
  1033.     printf("  (%d accounted for)",gprofit);
  1034.     gprofit = mpar1;
  1035.     }
  1036.     printf("\nEfficiency: %d%%\n",efficiency);
  1037.     printf("\nYour total dollar winnings will be your BASE value plus\n");
  1038.     printf("RATE times (efficiency - 100).\n");
  1039.     fflush(stdout);
  1040.     waitforreturn = 1;
  1041. #endif
  1042.     gend();
  1043. }
  1044.  
  1045.  
  1046. #define MAXKILLMES 9
  1047. static char * killmsg[MAXKILLMES] = {"killed by operator","response too late",
  1048.     "illegal response","bad message",".out file error","i/o failure",
  1049.     "monitor error","game abandoned","killed by DANI"};
  1050.  
  1051. static void
  1052. killed()
  1053. {
  1054.     char msg[60];
  1055.     if (mpar1==1 || mpar1==9) {
  1056.     strcpy(msg,"* ");
  1057.     strcat(msg,killmsg[mpar1-1]);
  1058.     }
  1059.     else if (mpar1>0 && mpar1<=MAXKILLMES) {
  1060.     strcpy(msg,"* killed by monitor -- ");
  1061.     strcat(msg,killmsg[mpar1-1]);
  1062.     }
  1063.     else if (mpar1 == 0)
  1064.     adios(WARNEXIT,1,1);
  1065.     else
  1066.     sprintf(msg,"*killed -- reason %d",mpar1);
  1067.     error(msg);
  1068. }
  1069.  
  1070.  
  1071. /* ------------ miscellaneous support and i/o routines ---------------- */
  1072.  
  1073. #ifdef PIPEBASED
  1074. #ifndef MSDOS
  1075. static void
  1076. pipesetup(argc,argv)
  1077. int argc;
  1078. char *argv[];
  1079. {
  1080. /* If the command line has 2 arguments they're file descriptors for
  1081.  * the pipes to the monitor.  If not, we use stdin and stdout */
  1082.     if (argc==3) {
  1083.     if (sscanf(argv[2],"%d",&outfd) != 1)
  1084.         error("output fd error");
  1085.     if (sscanf(argv[1],"%d",&infd) != 1)
  1086.         error("input fd error");
  1087.     }
  1088.     else if (hmtype==1)
  1089.     error("-a option needed");
  1090.     else if (argc<=1) {
  1091.     infd = fileno(stdin);
  1092.     outfd = fileno(stdout);
  1093.     }
  1094.     else
  1095.     error("wrong number of arguments");
  1096. }
  1097. #endif
  1098. #endif
  1099.  
  1100.  
  1101. #ifdef FILEBASED
  1102. static void
  1103. filesetup(argc)
  1104. int argc;
  1105. {
  1106.     if (argc>1)
  1107.     error("too many arguments");
  1108.  
  1109.     strcpy(inname,progname);
  1110.     strcat(inname,".in");
  1111.     strcpy(outname,progname);
  1112.     strcat(outname,".out");
  1113.  
  1114. /* open input file */
  1115.     infile = fopen(inname,"r");
  1116.     if (infile == NULL)
  1117.     error("can't open input file");
  1118. }
  1119. #endif
  1120.  
  1121.  
  1122. #ifdef INETBASED
  1123. #include "inet.c"
  1124. #endif
  1125.  
  1126.  
  1127. static void
  1128. initvars()    /* Initialize everything at start of round or period */
  1129. {
  1130.     RINT i;
  1131.     int maxtrades;
  1132.  
  1133.     t = 0;
  1134.     cbid = 0;
  1135.     coffer = 0;
  1136.     bidder = 0;
  1137.     offerer = 0;
  1138.     bstype = 0;
  1139.     price = 0;
  1140.     buyer = 0;
  1141.     seller = 0;
  1142.     ntrades = 0;
  1143.     lasttime = 0;
  1144.     mytrades = 0;
  1145.     mylasttime = 0;
  1146.     pprofit = 0;
  1147.     nobidoff = 0;
  1148.     bo = 0;
  1149.     nobuysell = 0;
  1150.     bs = 0;
  1151.     late = 0;
  1152.     clearbo();
  1153.     for (i=1; i<=nbuyers; i++)
  1154.     btrades[i] = 0;
  1155.     for (i=1; i<=nsellers; i++)
  1156.     strades[i] = 0;
  1157.     maxtrades = (nbuyers>nsellers?nsellers:nbuyers)*MAXTOKENS;
  1158.     for (i=1; i<=maxtrades; i++)
  1159.     prices[i] = 0;
  1160. }
  1161.  
  1162.  
  1163. static void
  1164. clearbo()    /* clears the bids and offers */
  1165. {
  1166.     RINT i;
  1167.     for (i=1; i<=nbuyers; i++)
  1168.     bids[i] = 0;
  1169.     for (i=1; i<=nsellers; i++)
  1170.     offers[i] = 0;
  1171.     nbids = 0;
  1172.     noffers = 0;
  1173. }
  1174.  
  1175.  
  1176. #ifdef DISPLAY
  1177. void
  1178. twolinehead()
  1179. {
  1180.     printf(
  1181.     "---------- round %-2d%c---------- period %d ---------- time %-2d%c",
  1182.     r,r>9?' ':'-',p,t,t>9?' ':'-');
  1183.     nput('-',20);
  1184.     nl();
  1185.     showcurrent();
  1186. }
  1187.  
  1188. void
  1189. showcurrent()
  1190. /*
  1191.  * Shows current tokens in standard place to right of line.  Also shows
  1192.  * current bid and current offer at left.
  1193.  */
  1194. {
  1195.     RINT i;
  1196.  
  1197.     fputs("cbid:",stdout);
  1198.     if (cbid == 0)
  1199.     fputs(" (none)  ",stdout);
  1200.     else if (bidder==id && role == 1)
  1201.     printf("%5d/YOU",cbid);
  1202.     else
  1203.     printf("%5d/B%-2d",cbid,bidder);
  1204.     printf(" coffer:");
  1205.     if (coffer == 0)
  1206.     fputs(" (none)  ",stdout);
  1207.     else if (offerer==id && role == 2)
  1208.     printf("%5d/YOU",coffer);
  1209.     else
  1210.     printf("%5d/S%-2d",coffer,offerer);
  1211.     fputs(" ",stdout);
  1212.  
  1213.     for (i=ntokens+1; i<=8; i++)    /* right justify */
  1214.     nput(' ',5);
  1215.     fputs("tokens:",stdout);
  1216.     for (i=1; i<=ntokens; i++)
  1217.     if (i>mytrades)
  1218.         printf("%5d",token[i]);
  1219.     else
  1220.         fputs("    -",stdout);
  1221.     nl();
  1222.     fflush(stdout);
  1223. }
  1224.  
  1225.  
  1226. void
  1227. showprices()
  1228. {
  1229.     RINT i;
  1230.  
  1231.     if (ntrades>0) {
  1232.     fputs("Summary of trade prices",stdout);
  1233.     if (mytrades>0)
  1234.         fputs(" (* = yours):",stdout);
  1235.     else
  1236.         putchar(':');
  1237.     for (i=1; i<=ntrades; i++)
  1238.         if (prices[i]>0)
  1239.         printf("%c%5d ",i%10==1?'\n':' ',prices[i]);
  1240.         else
  1241.         printf("%c%5d*",i%10==1?'\n':' ',-prices[i]);
  1242.     nl();
  1243.     }
  1244.     else
  1245.     puts("No trades");
  1246.     nl();
  1247.     fflush(stdout);
  1248. }
  1249.  
  1250.  
  1251. static void
  1252. nput(c,n)    /* does putchar(c) n times */
  1253. int c,n;
  1254. {
  1255.     RINT i;
  1256.  
  1257.     for (i=0; i<n; i++)
  1258.     putchar(c);
  1259. }
  1260.  
  1261.  
  1262. void
  1263. nl() { putchar('\n'); }
  1264. #endif
  1265.  
  1266.  
  1267. static void
  1268. getmess(ptype,ppar1,ppar2)    /* receives a message */
  1269. int *ptype,*ppar1,*ppar2;
  1270. {
  1271.     int n;
  1272. #ifdef FILEBASED
  1273.     n = fscanf(infile,"%d%d%d",ptype,ppar1,ppar2)-3;
  1274. #else
  1275. #ifdef MSDOS
  1276. /* experimental code */
  1277.     do {
  1278.     if (fgets(auxbuf,100,stdaux) != NULL) {
  1279.         auxbuf[99] = EOS;
  1280.         if (sscanf(auxbuf,"%d%d%d",ptype,ppar1,ppar2) == 3)
  1281.         n = 0;
  1282.         else {
  1283.         fputs(auxbuf,stdout);
  1284.         auxbuf[5] = EOS;
  1285.         if (strcmp(auxbuf,"Enter") == 0) {
  1286.             fgets(auxbuf,100,stdin);
  1287.             fputs(auxbuf,stdaux);
  1288.         }
  1289.         n = 1;
  1290.         }
  1291.     else
  1292.         n = -1;
  1293.     } while (n>0) ;
  1294. #else
  1295.     char buf[17];
  1296.     n = READ(infd,buf,16)-16;
  1297.     if (n == 0) {
  1298.     buf[16] = EOS;
  1299.     n = sscanf(buf,"%d%d%d",ptype,ppar1,ppar2)-3;
  1300.     }
  1301. #endif
  1302. #endif
  1303.     if (n)
  1304.     error("*connection broken");
  1305. }
  1306.  
  1307.  
  1308. static void
  1309. expect(expected,ppar1,ppar2)    /* receives a message, checks type */
  1310. int expected,*ppar1,*ppar2;
  1311. {
  1312.     int actual;
  1313.     char emess[60];
  1314.     
  1315.     getmess(&actual,ppar1,ppar2);
  1316.     if (actual != expected) {
  1317.     sprintf(emess,"protocol violation -- expected %d, actual %d",
  1318.         expected,actual);
  1319.     error(emess);
  1320.     }
  1321. }
  1322.  
  1323.  
  1324. static void
  1325. sendmess(msgtype,par)
  1326. int msgtype,par;
  1327. /*
  1328.  * Sends a message.  In the FILEBASED case it opens the output file,
  1329.  * writes the message, saves the data (to the same file), and quits.
  1330.  * In the PIPEBASED or INETBASED case it just writes the data to the
  1331.  * pipe/socket.  Low-level I/O is used for ease of VMS compatability.
  1332.  */
  1333. {
  1334.  
  1335. #ifndef FILEBASED
  1336. /* write the message */
  1337. #ifdef VMS
  1338.     char msg[13];
  1339.     sprintf(msg,"%5d%5d\r\n",msgtype,par);
  1340.     WRITE(outfd,msg,12);
  1341. #else
  1342. #ifdef MSDOS
  1343.     fprintf(stdaux,"%5f%5d\n",msgtype,par);
  1344. #else
  1345.     char msg[12];
  1346.     sprintf(msg,"%5d%5d\n",msgtype,par);
  1347.     WRITE(outfd,msg,11);
  1348. #endif
  1349. #endif
  1350.  
  1351. #else
  1352. /* close input file */
  1353.     if (infile != NULL) fclose(infile);
  1354.     infile = NULL;
  1355.  
  1356. /* open output file if not already open */
  1357.     if (outfile == NULL) {
  1358. #ifdef VMS
  1359.     remove(outname);    /* remove previous version if any */
  1360. #endif
  1361.     outfile = fopen(outname,"w");
  1362.     if (outfile == NULL)
  1363.         error("*can't open output file");
  1364.     }
  1365.  
  1366. /* write the message */
  1367.     fprintf(outfile,"%5d%5d\n",msgtype,par);
  1368.  
  1369. /* return without doing savedata if QUIT or REFUSE */
  1370.     if (msgtype == QUIT || msgtype == REFUSE) return;
  1371.  
  1372. /* save our variables unless TEST */
  1373.     if (msgtype != TEST) {
  1374.     savefile = outfile;
  1375.     savedata();
  1376.     }
  1377.  
  1378. /* exit */
  1379.     adios(GOODEXIT,0,0);
  1380. #endif
  1381. }
  1382.  
  1383.  
  1384. static void
  1385. stripcopy(result,input,n)
  1386. char *result,*input;
  1387. int n;
  1388. /*
  1389.  * Like strncpy, but for file names.  Strips any directory prefix (with /
  1390.  * or \ or : or ] separators), and any extension(s) with . separator.
  1391.  */
  1392. {
  1393.     char *ptr,*first;
  1394.     char c;
  1395.  
  1396.     ptr = input;
  1397.     first = input;
  1398.     while ((c = *ptr++) != EOS) 
  1399.     if (c == '/' || c == '\\' || c == ':' || c == ']')
  1400.         first = ptr;
  1401.     while ((c = *first++) != EOS && c != '.' && --n > 0)
  1402.     *result++ = c;
  1403.     *result = EOS;
  1404. }
  1405.  
  1406.  
  1407. #ifdef FILEBASED
  1408. void
  1409. readarray(array,n)    /* read array from savefile */
  1410. int *array,n;
  1411. {
  1412.     RINT i;
  1413.     for (i=1; i<=n; i++)
  1414.     fscanf(savefile,"%d ",array+i);
  1415. }
  1416.  
  1417.  
  1418. void
  1419. writearray(array,n)    /* write array to savefile */
  1420. int *array,n;
  1421. {
  1422.     RINT i;
  1423.     for (i=1; i<=n; i++)
  1424.     fprintf(savefile,"%d%c",array[i],(i%10)?' ':'\n');
  1425.     if (n%10) putc('\n',savefile);
  1426. }
  1427. #endif
  1428.  
  1429.  
  1430. static void
  1431. randset()
  1432. /*
  1433.  * Set up random number generator, taking care that different players
  1434.  * starting at the same second, and file players on successive steps,
  1435.  * will have different seeds.
  1436.  */
  1437. {
  1438. #ifndef THINKC3
  1439.     time_t time();
  1440. #endif
  1441.     double drand();
  1442.     int seed,i;
  1443.  
  1444.     seed = (int) (time((time_t *)0)&32767);
  1445.     seed ^= (id*1319 ^ (id&3)*9929 ^ role*10343 ^ (t&15)*1933 ^ mtype*977);
  1446. #ifdef ANSI
  1447.     srand((unsigned int) (seed&RAND_MAX));
  1448. #else
  1449.     srand(seed&RAND_MAX);
  1450. #endif
  1451.     for (i=0; i<13; i++)
  1452.     drand();        /* exercise it */
  1453. }
  1454.  
  1455.  
  1456. double
  1457. drand()
  1458. /*
  1459.  * Uniform [0,1) random number generator, for use by user's strategies.
  1460.  */
  1461. { return ((double) rand())/(((double) RAND_MAX) + 1.0); }
  1462.  
  1463.  
  1464. void
  1465. error(msg)    /* routine for unexpected fatal error */
  1466. char * msg;
  1467. {
  1468.     char myname[7];
  1469.     char *ptr;
  1470.  
  1471.     if (noblock)
  1472.     resetterm();
  1473.     if (*msg != EOS) {
  1474.     ptr = (*msg=='*')? msg+1: msg;
  1475.     if (id>0 && (role==1 || role==2))
  1476.         sprintf(myname," (%c%d)",(role==1)?'B':'S',id);
  1477.     else
  1478.         myname[0] = EOS;
  1479.     fprintf(stderr,"\n*** error in '%s'%s: %s\n",
  1480.         progname,myname,ptr);
  1481.     }
  1482. #ifdef DISPLAY_OR_INET
  1483.     if (gameid > 0)
  1484.     fprintf(stderr,"Exit from game %d\n",gameid);
  1485. #endif
  1486.     if (*msg != '*')
  1487.     sendmess(QUIT,*msg==EOS?0:1);
  1488.     adios(*msg==EOS?GOODEXIT:BADEXIT,1,*msg=='*');
  1489. }
  1490.  
  1491.  
  1492. static void
  1493. adios(status,delin,delout)
  1494. int status,delin,delout;
  1495. /*
  1496.  * Routine for all exits.  Restores terminal, deletes .in and/or .out file
  1497.  * as requested, exits with status.
  1498.  */
  1499. {
  1500.     if (noblock)
  1501.     resetterm();
  1502. #ifdef THINKC
  1503.     if (status != GOODEXIT || waitforreturn) {
  1504.     printf("------- Press Return to Continue -------\n");
  1505.     getchar();
  1506.     }
  1507. #endif
  1508. #ifdef FILEBASED
  1509.     if (infile!=NULL) fclose(infile);
  1510.     if (outfile!=NULL) fclose(outfile);
  1511. #ifdef ALWAYSDELIN
  1512.     delin = 1;
  1513. #endif  
  1514.     if (delout) REMOVE(outname);
  1515.     if (delin) REMOVE(inname);
  1516. #endif
  1517.     exit(status);
  1518. }
  1519.  
  1520.  
  1521. void header()
  1522. {
  1523.     printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
  1524.     printf("            ############################################\n");
  1525.     printf("            #          Santa Fe Double Auction         #=\n");
  1526.     printf("            ############################################=-\n");
  1527.     printf("            #              UNIX Version 1.0            #=-.\n");
  1528.     printf("            #               TCP/IP required            #=-.\n");
  1529.     printf("            #                                          #=-.\n");
  1530.     printf("            #                   1992                   #=-.\n");
  1531.     printf("            #            Santa Fe Institute            #=-.\n");
  1532.     printf("            #        Economic Science Laboratory       #=-.\n");
  1533.     printf("            #        National Science Foundation       #=-.\n");
  1534.     printf("            ############################################=-.\n");
  1535.     printf("             ============================================-.\n");
  1536.     printf("              --------------------------------------------.\n");
  1537.     printf("               ............................................\n");
  1538.  
  1539. } /* header */
  1540.  
  1541. void get_gamedata(fddad)
  1542. int fddad;
  1543. {
  1544.     char string[200];
  1545.     int a,b,c,d,e;
  1546.  
  1547.     if(sock_gets(fddad,string,200) == -1)
  1548.         error("connection broken while reading gamedata");
  1549.     sscanf(string,"%f %f %d %d %d %d %d %d\n", &payment_base,
  1550.         &payment_rate, &a, &b, &c, &d, &e, &clearingrule);
  1551.     rantok_main(a,b,c,d,e);
  1552.     if(a == 0) havegametype = 0; /* FALSE */
  1553.     else havegametype = 1; /* TRUE */
  1554.  
  1555. } /* get_gamedata */
  1556.  
  1557. void get_gamehist(fddad)
  1558. int fddad;
  1559. {
  1560.     FILE *fp;
  1561.     char string[200];
  1562.     int empties = 0;
  1563.     if((fp = fopen("gamehist.dat","w")) == NULL)
  1564.         error("couldn't open gaemhist.dat for writing");
  1565.     while(0==0)
  1566.     {
  1567.         if(sock_gets(fddad,string,200) < 0)
  1568.             error("connection broken while reading gamedata");
  1569.         if(strncmp(string,"end",3) == 0 ) {
  1570.             fclose(fp);
  1571.             return;
  1572.         } else {
  1573.             fprintf(fp,"%s\n",string);
  1574.         }
  1575.         if(strlen(string) == 0) {
  1576.             sleep(1);
  1577.             empties++;
  1578.             if(empties>50) {
  1579.                 fclose(fp);    
  1580.                 return;
  1581.             }
  1582.         }
  1583.     } /* while */
  1584.  
  1585. } /* get_gamehist */
  1586.  
  1587. void get_players(fddad)
  1588. int fddad;
  1589. {
  1590.     FILE *fp;
  1591.     char string[200];
  1592.     int empties = 0;
  1593.     if((fp = fopen("players.dat","w")) == NULL)
  1594.         error("couldn't open gaemhist.dat for writing");
  1595.     while(0==0)
  1596.     {
  1597.         if(sock_gets(fddad,string,200) < 0)
  1598.             error("connection broken while reading gamedata");
  1599.         if(strncmp(string,"end",3) == 0 ) {
  1600.             fclose(fp);
  1601.             return;
  1602.         } else {
  1603.             fprintf(fp,"%s\n",string);
  1604.         }
  1605.         if(strlen(string) == 0) {
  1606.             sleep(1);
  1607.             empties++;
  1608.             if(empties>50) {
  1609.                 fclose(fp);    
  1610.                 return;
  1611.             }
  1612.         }
  1613.     } /* while */
  1614.  
  1615. } /* get_players */
  1616.  
  1617. static void
  1618. sleep(secs)
  1619. int secs;
  1620. {
  1621.  
  1622.         long start,end,ltime;
  1623.         start = time(<ime);
  1624.         end = start + secs;
  1625.         do {;} while(time(<ime)<end);
  1626.  
  1627. }
  1628.  
  1629. int sock_gets(sd,buf,len)
  1630. int sd, len;
  1631. char *buf;
  1632. {
  1633.     char *mptr;
  1634.     int i=0;
  1635.  
  1636.     mptr = buf;
  1637.     while (read(sd,mptr,1) == 1 && *mptr != '\n' && i<len-1)
  1638.     {
  1639.         mptr++;
  1640.         i++;
  1641.     }
  1642.     if (*mptr != '\n')
  1643.         return -1;
  1644.     *mptr = '\0';
  1645.     return i;
  1646.  
  1647. void menu()
  1648. {
  1649.     int choice = 0;
  1650.     char reply[128];
  1651.  
  1652.     while(choice != 7) {
  1653.     print_menu();
  1654.     printf("\nYour choice? ");
  1655.     gets(reply);
  1656.     choice = atoi(reply);
  1657.     printf("\n");
  1658.     switch(choice) {
  1659.         case 1: /* show table of random draws */
  1660.         if(!havegametype) {
  1661.             printf("You are not allowed to view token information in this game.\n\n");
  1662.             break;
  1663.         }
  1664.         intro_chart();
  1665.         break;
  1666.         case 2: /* show payment rates */
  1667.         show_payment_rates();
  1668.         break;
  1669.         case 3: /* show clearing rule */
  1670.         show_clearingrule();
  1671.         break;
  1672.         case 4: /* read descriptions of robot player strategies */
  1673.         show_descriptions();
  1674.         break;
  1675.         case 5: /* show players.dat */
  1676.         show_players();
  1677.         break;
  1678.         case 6: /* show gamehist.dat */
  1679.         show_gamehist();
  1680.         break;
  1681.         case 7: /* begin session */
  1682.         printf("\nBeginning session with AZTE now....\n");
  1683.         break;
  1684.         case 8: /* quit */
  1685.         sendmess(QUIT,0);
  1686.         exit(0);
  1687.         default:
  1688.         printf("Please choose a number between 1 and 8.\n\n\n");
  1689.     } /* switch */
  1690.     fflush(stdin);
  1691.     } /* end while */
  1692. } /* menu */
  1693.  
  1694. void print_menu()
  1695. {
  1696.     puts(" ");
  1697.     puts("     ===============================================================");
  1698.     puts("     = AZTE Menu Options:                                          =");
  1699.     puts("     ===============================================================");
  1700.     puts("     = 1. Show Table of Random Value Token Draws (Supply & Demand) =");
  1701.     puts("     = 2. Show Payment Rates for Today's Game                      =");
  1702.     puts("     = 3. Display the Clearing Rule                                =");
  1703.     puts("     = 4. Read Descriptions of Robot Player Strategies             =");
  1704.     puts("     = 5. Show Your Current Robot Opponents                        =");
  1705.     puts("     = 6. Review Game History                                      =");
  1706.     puts("     = 7. Begin a Session with Arizona Token Exchange now          =");
  1707.     puts("     = 8. Quit and exit.                                           =");
  1708.     puts("     ===============================================================");
  1709.     puts(" ");
  1710.  
  1711. } /* print_menu */
  1712.  
  1713. void show_payment_rates()
  1714. {
  1715.     printf("BASE = $%.2f     RATE = $%.2f\n\n",payment_base,payment_rate);
  1716.     printf("In today's game you will receive a base payment of $%.2f\n",
  1717.         payment_base);
  1718.     printf("plus $%.2f times (your efficiency minus 100)\n",payment_rate);
  1719.     printf("\n RATE * ( %% Efficiency - 100 )\n");
  1720.  
  1721.     printf("\nPress Enter/Return to continue....\n");
  1722.     waitkey();
  1723. }
  1724.  
  1725. void show_clearingrule()
  1726. {
  1727.     char therule[20];
  1728.  
  1729.     if(clearingrule == 0)
  1730.         strcpy(therule,"RANDOM");
  1731.     else
  1732.         strcpy(therule,"AVERAGE");
  1733.  
  1734.     printf("\nToday's game will use the %s clearing rule.\n", therule);
  1735.     printf("\nPress Enter/Return to continue....\n");
  1736.     waitkey();
  1737. }
  1738.  
  1739. void show_descriptions()
  1740. {
  1741.     display_file("robots.txt");
  1742.     printf("\n\nThis file (\"robots.txt\") can also be viewed outside the program.\n");
  1743.  
  1744. } /* show_descriptions */
  1745.  
  1746. void show_players()
  1747. {
  1748.     display_file("players.dat");
  1749.  
  1750. }
  1751.  
  1752. void show_gamehist()
  1753. {
  1754.     display_file("gamehist.dat");
  1755.  
  1756. }
  1757.  
  1758. void display_file(filename)
  1759. char * filename;
  1760. {
  1761.     FILE *fd;
  1762.     int quitnow=0,total,line=0;
  1763.     char *pt, buf[130],string[128];
  1764.  
  1765.     fd = fopen(filename,"r");
  1766.     if(fd == NULL) {
  1767.         printf("Could not open %s for reading.\n", filename);
  1768.         printf("Press Enter/Return to return to the main menu...\n");
  1769.         waitkey();
  1770.         return;
  1771.     }
  1772.     total = line_count(fd);
  1773.     if(total == 0) total = 1;
  1774.  
  1775.     rewind(fd);
  1776.     fgets(buf,128,fd);
  1777.     while(!feof(fd) && !quitnow) {
  1778.         for(pt = buf;*pt != '\n' && *pt; pt++);
  1779.         *pt = '\0';
  1780.         puts(buf);
  1781.         fgets(buf,128,fd);
  1782.         if(feof(fd)) break;
  1783.         line++;
  1784.         if(line%23 == 0) {
  1785.             printf("--More--(%d%%) <Press Enter/Return to continue, Q to quit>",
  1786.                 line*100/total);
  1787.             gets(string);
  1788.             if(*string=='q'||*string=='Q') quitnow = 1;
  1789.         }
  1790.     }
  1791.     fclose(fd);
  1792.     puts(" ");
  1793.     if(quitnow) return;
  1794.     printf("Press Enter/Return to continue....\n");
  1795.     waitkey();
  1796.  
  1797. } /* display_file */
  1798.  
  1799. int line_count(fd)
  1800. FILE * fd;
  1801. {
  1802.     int count = 0;
  1803.     char buf[130];
  1804.  
  1805.     rewind(fd);
  1806.     while(!feof(fd)) {
  1807.         count++;
  1808.         fgets(buf,128,fd);
  1809.     }
  1810.     return count;
  1811.  
  1812. } /* line_count */
  1813.  
  1814. void waitkey()
  1815. {
  1816.     getchar();
  1817.     fflush(stdin);
  1818. } /* waitkey */
  1819.  
  1820.